#pragma once

#include "GetMachineInformation.hpp" //��ȡ������Ϣ
#include "Bash64.hpp"
#include "AES.hpp"

#include "curl/curl.h"  
#include <unistd.h>
#include <sys/types.h>
#include <iostream>
#include <sys/stat.h>
using std::cout;
using std::endl;

#ifndef libSocket_H
#define libSocket_H

class libConnect :public libBash64, public libGetMachineInformation, public libAES
{
public:
	int Connect(); //������0 ������������Ƭ ������1 �򱨴���ʾ��֤ʧ��
private:
	int ReadFile(); //��ȡ������Ȩ�ļ� ��������֤�ɹ� �򲻽���Զ����֤ ����֮
	int DeleteFile();
	int ConnectServer(); //���Ĭ����Ȩ�ļ�������   �ύ ���� ��Ϣ���������ͨ����֤  ��ȡ��Ӧ��Կ�ѻ�ȡ�ı�����Ϣ���ܺ����Կ�ͼ��ܺ����Ϣһ������ /usr/local/seg/segment.auth

	static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid);

	string PC_info; //������Ϣ �磺�����ַ� + �����汾 + mac + IP + ϵͳOS��Ϣ
	string file_index{ "#jasdqwedgjnfg5868627ewrrfew#" }; //file�е�������Ϣ�ļ����־

};
#endif // !libSocket_H

int libConnect::Connect()
{
	int ret;
	PC_info = GetMachineInformation2();
	//	std::cout << PC_info << std::endl;
	//��֮  �Ȱѻ�����Ϣ��ȡ��
	ret = ReadFile();
	if (0 != ret)
	{
		DeleteFile();//delete auth
		ret = ConnectServer();
		if (ret)
		{
			return 1;
		}
	}
	//������ 
	if (-1 == ret)
	{
		cout << "INDEX_542345" << endl;
		return 1;
	}
	if (-2 == ret)
	{
		cout << "INDEX_542345" << endl;
		return 1;
	}
	if (-3 == ret)
	{
		cout << "INDEX_542345" << endl;
		return 1;
	}
	if (-4 == ret)
	{
		cout << "INDEX_542345" << endl;
		return 1;
	}
	//
	return 0;
}

int libConnect::ReadFile()
{
	int ret;
	std::ifstream i;
	i.open("/usr/local/seg/segment.auth", std::ios::in | std::ios::binary);
	if (!i.is_open())
	{
		//		printf("Failed open /usr/local/seg/segment.auth.\n");  //
		return 1; //û��ͬ���ļ�  �������������ͨ����֤
	}
	//����Ӧ�ö�ȡ�ļ����� ������c_info֮��
	std::stringstream ss;
	ss << i.rdbuf();
	i.clear(); //��һ����Ҫ
	i.close();
	//########################�����ȡ�������������ļ�����
	string file_date;
	file_date.assign(ss.str()); //  ע����ô��ת�������Ƿ��б仯��Ӧ��
	int file_index_num = file_date.find(file_index);
	//server���ص�ȫ����Ϣ
	string file_info_all_bash64;  //����server ������Ϣ����Ȩ���{0|1}  + ������Կ X  + ��ǰʱ�� + ��Ȩʱ������
	file_info_all_bash64.assign(file_date, 0, file_index_num);
	string file_info_all;
	file_info_all = Decode(file_info_all_bash64.c_str(), file_info_all_bash64.size(), ret);
	//��Ȩ���{0|1} 
	int index1 = file_info_all.find("|", 0);
	if (index1 < 0)
	{
		cout << "INDEX_58641" << endl;
		return -3;
	}
	string server_result;
	server_result.assign(file_info_all, 0, index1);
	if (server_result != "1")
	{
		cout << "INDEX_45678" << endl;
		return -1;//������֤��Ȩʧ��
	}
	//������Կ X 
	int index2 = file_info_all.find("|", index1 + 1); //�±�λ��ע�ⲻҪ�����
	if (index2 < 0)
	{
		cout << "INDEX_465778" << endl;
		return -3;
	}
	string file_aesx;
	file_aesx.assign(file_info_all, index1 + 1, index2 - index1 - 1);
	//��ǰʱ��
	int index3 = file_info_all.find("|", index2 + 1);
	if (index3 < 0)
	{
		cout << "INDEX_1235" << endl;
		return -3;
	}
	string server_date;
	server_date.assign(file_info_all, index2 + 1, index3 - index2 - 1);
	while (server_date.length() > 10) //��λ��������  �����ǲ���ϸ��ȥ���������ڰ汾���⣬�ƺ���һ��汾�͸������⣬�Գ�һ��ı���������  ������ʱ������������� ����Ҫ����һ������ʱ�ı�������
	{
		server_date.pop_back();
	}
	//��Ȩʱ������
	string file_time;
	file_time.assign(file_info_all, index3 + 1, file_info_all.length() - index3 - 1);
	//��֤��Ч�ڳ�ʱ
	time_t  file_data_m = atoi(server_date.c_str());
	time_t  file_time_m = atoi(file_time.c_str()) * 24 * 60 * 60;
	time_t  PC_data_m = time(NULL);
	ret = (PC_data_m - file_data_m) < file_time_m ? 0 : 1;
	if (ret)
	{
		cout << "INDEX_547635" << endl;
		return 1; //��������Ч�ڹ��� �����ӷ�����������ȡһ����֤
	}
	//������ȡ�ļ��еĴ��ԱȻ�����Ϣ
	string errMsg;
	string file_PC_info_bash64_aes;
	file_PC_info_bash64_aes.assign(file_date, file_index_num + file_index.length(), file_date.length() - file_index_num - file_index.length()); //
	string server_PC_info_bash64;
	while (file_aesx.length() != AES_KEY_LENGTH_16)
	{
		file_aesx.append("1");
	}
	ret = decrypt4aes(file_PC_info_bash64_aes, file_aesx, server_PC_info_bash64, errMsg);
	string file_PC_info;
	file_PC_info = Decode(server_PC_info_bash64.c_str(), server_PC_info_bash64.size(), ret);
	//	cout << PC_info << endl /*<< file_PC_info */<< endl;

	string  file_PC_info_origin;
	ret = file_PC_info.find(s_Check_KEY);
	if (ret < 0)
	{
		cout << "INDEX_5681235" << endl;
		return -3;//������֤������
	}
	file_PC_info_origin.assign(file_PC_info, ret, file_PC_info.length() - ret);
	//	cout << s1 << endl << s2 << endl;
	if (PC_info != file_PC_info_origin)
	{
		cout << "INDEX_908925" << endl;
		return -3;//������֤������
	}
	return 0;
}

inline int libConnect::DeleteFile()
{
	remove("/usr/local/seg/segment.auth"); //�������Ȩ
	return 0;
}

int libConnect::ConnectServer()
{
	int ret;
	curl_global_init(CURL_GLOBAL_ALL);
	//
	CURL *curl;
	CURLcode res;

	string PC_info_bash64;
	PC_info_bash64 = Encode((const unsigned char*)PC_info.c_str(), PC_info.size());
	string server_info_bash64;
	///##################################################################
	printf("connect server.\n");
	curl = curl_easy_init();
	if (curl) //ȷ������
	{
		//		curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.1.59:8180/ai-segmenterAuth/OAuthServer/accessKey.do");//ControlIP ����ʵ���ֶ����÷�������ַ 
		//curl_easy_setopt(curl, CURLOPT_URL, "http://dajljp29sd.com:8082/aisegmenterAuth/OAuthServer/accessKey.do");//�ɽӿ� �Կ���
		curl_easy_setopt(curl, CURLOPT_URL, "http://seg.dajljp29sd.com/OAuthServer/accessKey.do");//�½ӿ� 
		curl_easy_setopt(curl, CURLOPT_POST, 1); //?

		curl_slist *plist = curl_slist_append(NULL,
			"Content-Type:application/octet-stream;charset=UTF-8"); //�������������Э�鷽ʽ
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, plist);

		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, PC_info_bash64.c_str());
		curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); //����ص�����
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&server_info_bash64);
		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);//���ӳ�ʱ

		res = curl_easy_perform(curl); //���ص�res��һ���ж� �������ϵ�����ר�Ŵ�ӡһ�� 
		if (CURLE_OK != res) //ͨѶ���ɹ�
		{
			printf("Error curl_easy_perform , return %d.\n", res);
			curl_easy_cleanup(curl);
			curl_global_cleanup();
			return 1;
		}
		//ȷ���ر�
		curl_easy_cleanup(curl);
	}
	curl_global_cleanup();
	std::cout << "Connect over!" << std::endl;
	///##################################################################
	string server_info;
	server_info = Decode(server_info_bash64.c_str(), server_info_bash64.size(), ret);
	//	cout << "server_info"<<server_info << endl; //1|ystripinfo|1478770534954|30    �������
	//��Ȩ���{0|1} 
	int index1 = server_info.find("|", 0);
	if (index1 < 0)
	{
		cout << "INDEX_756635" << endl;
		return -3;
	}
	string server_result;
	server_result.assign(server_info, 0, index1);
	//	cout <<"server_result" <<server_result << endl;
	if (server_result != "1")
	{
		cout << "INDEX_542345" << endl;
		return -1;//������֤��Ȩʧ��
	}
	//������Կ X 
	int index2 = server_info.find("|", index1 + 1); //�±�λ��ע�ⲻҪ�����
	if (index2 < 0)
	{
		cout << "INDEX_845" << endl;
		return -3;
	}
	string server_aesx;
	server_aesx.assign(server_info, index1 + 1, index2 - index1 - 1);
	//	cout <<"server_aesx" <<server_aesx << endl;
	//��ǰʱ��
	int index3 = server_info.find("|", index2 + 1);
	if (index3 < 0)
	{
		cout << "INDEX_87446" << endl;
		return -3;
	}
	string server_date;
	server_date.assign(server_info, index2 + 1, index3 - index2 - 1);
	while (server_date.length() > 10) //��λ��������
	{
		server_date.pop_back();
	}
	//	cout << "server_date"<<server_date << endl;
	//��Ȩʱ������
	string server_time;
	server_time.assign(server_info, index3 + 1, server_info.length() - index3 - 1);
	//	cout << "server_time"<<server_time << endl;
	//��֤��Ч�ڳ�ʱ
	time_t  server_data_m = atoi(server_date.c_str());
	time_t  server_time_m = atoi(server_time.c_str()) * 24 * 60 * 60;
	time_t  PC_data_m = time(NULL);
	ret = (PC_data_m - server_data_m) < server_time_m ? 0 : 1;
	if (ret)
	{
		cout << "INDEX_123343" << endl;
		return -2;//������֤��Ч�ڳ�ʱ
	}
	// ##################################################################���뱾���ļ�  ������΢�鷳һ�� sheng���˻�û��ֱ��д��������ȵ��ļ�
	if (access("/usr/local/seg/", F_OK) == -1)  //������Ҫ���ע��һ��  ������Ҫ��root�˺��������������������
	{
		if (mkdir("/usr/local/seg", 0777))//��������ھ���mkdir����������
		{
			cout << "creat file bag failed!!!" << endl;
			cout << "INDEX_13355" << endl;
			return -4;
		}
	}

	std::ofstream ofs;
	ofs.open("/usr/local/seg/segment.auth", std::ios::out | std::ios::trunc | std::ios::binary);
	if (!ofs.is_open())
	{
		cout << "INDEX_523785" << endl;
		return -4; // ��΢����һ�� д�ļ���λ��
	}
	//����Ӧ�ö�ȡ�ļ����� ������c_info֮��
	std::stringstream ss;
	ss << server_info_bash64; //д�뱾�� ֮��Ӹ���ʶ ������Ȩ��Ϣ��AES���ܺ������
	ss << file_index; //��ʶ��ò����׿������� ������Ҫ�㹻�� ���������ĸ��뿪 ��Ȩ��Ϣ������

	string PC_bash64_AES_info_local;
	{
		string msg_error;
		while (server_aesx.length() != AES_KEY_LENGTH_16)
		{
			server_aesx.append("1");
		}
		//		cout << server_aesx << endl;
		string PC_info_local;
		PC_info_local.assign("#qianzhirongyu#");
		PC_info_local.append(PC_info);
		string PC_info_bash64_local;
		PC_info_bash64_local = Encode((const unsigned char*)PC_info_local.c_str(), PC_info_local.size());
		ret = encrypt4aes(PC_info_bash64_local, server_aesx, PC_bash64_AES_info_local, msg_error); //	
		std::cout << msg_error << std::endl;
	}
	ss << PC_bash64_AES_info_local; //

	ofs << ss.str();
	ofs.clear(); //��һ����Ҫ
	ofs.close();

	return 0;
}

size_t libConnect::OnWriteData(void * buffer, size_t size, size_t nmemb, void * lpVoid)
{
	std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
	if (NULL == str || NULL == buffer)
	{
		return -1;
	}

	char* pData = (char*)buffer;
	str->append(pData, size * nmemb);
	return nmemb;
}
